﻿// =====================================================================
// Sprite.cs
// by Hushel Roberts
// =====================================================================

using System;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using MathUtil;
using Physics;
using Geometry;

namespace Tank
{
    public class Sprite
    {

        // Member Data
        protected string textureID;     // Used to identify the content to be used with this sprite
        protected string name;
        protected float drawScale;
        protected Vector2 origin;
        protected SoundEffect sound;
        private float drag;
        private float forceMag;
        private float maxVel;
        private float maxAccel;
        private Vector2 pos;                // Center position
        private Vector2 prevPos;            // Previous position
        private Vector2 velocity;
        private Vector2 accel;
        private PhysicsType physType;


        public Sprite(Vector2 _pos, float _maxVel, float _maxAccel, float _drag, string _textureID, string _name)
        {
            drag = _drag;
            pos = new Vector2(_pos.X, _pos.Y);
            prevPos = new Vector2(_pos.X, _pos.Y);
            maxAccel = _maxAccel;
            maxVel = _maxVel;
            textureID = _textureID;     
            name = _name;
            forceMag = 1.0f;
            physType = PhysicsType.PHYS_NONE;
            drawScale = 1.0f;
            origin = new Vector2();
            // TODO - do we want an angle here to draw sprite rotated
        }

        public virtual void Update(float deltaTime)
        {
            if (accel.X != 0 || accel.Y != 0)
            {
                velocity += accel;
                accel = new Vector2(0.0f, 0.0f);
            }

            prevPos = pos;
            pos += (velocity * deltaTime);

            ApplyDrag();

            if (MathLib.NearZero(velocity))
            {
                MathLib.ZeroVector2(velocity);
            }
        }

        public virtual void Draw(SpriteBatch spriteBatch)
        {
            Vector2 drawPos = new Vector2();
            Texture2D texture = World.Instance.GetTexture(textureID);
            drawPos.X = Position.X - texture.Width * .5f;
            drawPos.Y = Position.Y - texture.Height * .5f;
            spriteBatch.Draw(texture, drawPos, Color.White);
        }

        public void ApplyDrag()
        {
            velocity -= (velocity * drag);
        }

        public void ApplyVelocity(Vector2 _maxVel)
        {
            if (physType == PhysicsType.PHYS_STATIC || physType == PhysicsType.PHYS_STATIC_FORCEAPPLIER)
            {
                return;
            }
            velocity += _maxVel;
        }

        public void ApplyAccel(Vector2 _maxAccel)
        {
            if (physType == PhysicsType.PHYS_STATIC || physType == PhysicsType.PHYS_STATIC_FORCEAPPLIER)
            {
                return;
            }
            accel += _maxAccel;
        }

        public Vector2 Position
        {
            get { return pos; }
            set { pos = value; }
        }

        public Vector2 Origin
        {
            set { origin = value; }
        }

        public Vector2 PrevPos
        {
            get { return prevPos; }
            set { prevPos = value; }
        }

        public Vector2 Velocity
        {
            get { return velocity; }
            set { velocity = value; }
        }

        public float Drag
        {
            set { drag = value; }
        }

        public float DrawScale
        {
            set { drawScale = value; }
            get { return drawScale; }
        }

        public string TextureID
        {
            set { textureID = value; }
            get { return textureID; }
        }

        public string Name
        {
            set { name = value; }
            get { return name; }
        }

        public PhysicsType PhysType
        {
            set { physType = value; }
            get { return physType; }
        }

        public float ForceMag
        {
            set { forceMag = value; }
            get { return forceMag; }
        }
		public Vector2 Accel
		{
			get { return accel; }
		}
    }

    
    public class CircularSprite : Sprite
    {
        

        private BoundingSphere spriteBS;
        private float radius;
        private float elasticity;
        protected int value;               

        public CircularSprite(Vector2 _pos, float _maxVel, float _maxAccel, float _drag, string _textureID, string _name, float _radius)
            : base(_pos, _maxVel, _maxAccel, _drag, _textureID, _name)
        {
            radius = _radius;
            elasticity = 1.0f;
            Vector3 center = new Vector3(_pos.X, _pos.Y, 0.0f);
            spriteBS = new BoundingSphere(center, radius);
            value = 20;
        }

        public override void Update(float deltaTime)
        {
            base.Update(deltaTime);

            spriteBS.Center.X = Position.X;
            spriteBS.Center.Y = Position.Y;
        }

        public BoundingSphere BoundSphere
        {
            get { return spriteBS; }
        }

        public int Value
        {
            get { return value; }
        }

        public float Elasticity
        {
            get { return elasticity; }
        }
    }

    public enum SquareSpriteColor
    {
        GREEN,
        BLUE,
        ORANGE,
        RED
    }

    public enum SquareSpriteShape
    {
        SQUARE,
        SMALLRECT,
        MEDRECT,
        LARGERECT
    }

    public class SquareSprite : Sprite
    {
        // Members Only
        protected SquareSpriteShape shape;
        protected SquareSpriteColor color;
        protected BoundingBox spriteBB;
        protected float width;
        protected float height;
        protected Rectangle rect;
        protected Frame currFrame;      // Boundry for what part of image is drawn
        protected float rotation;       // Angle in radians
        static Random rand = new Random ();
        List<float> randomAngles;


        public SquareSprite(Vector2 _pos, float _maxVel, float _maxAccel, float _drag, string _textureID, string _name, float _width, float _height, SquareSpriteColor _color, SquareSpriteShape _shape) 
            : base(_pos, _maxVel, _maxAccel, _drag, _textureID, _name)
        {
            shape = _shape;
            color = _color;
            width = _width;
            height = _height;
            Vector3 min = new Vector3(_pos.X - width * 0.5f, _pos.Y - height * 0.5f, 0.0f);
            Vector3 max = new Vector3(_pos.X + width * 0.5f, _pos.Y + height * 0.5f, 0.0f);
            spriteBB = new BoundingBox(min, max);
            rect = new Rectangle((int)(_pos.X - _width / 2), (int)(_pos.Y - _height / 2), (int)_width, (int)_height);

            // Not Used: collitions dont work with rotated boxes // rotation = randomRotation();

            // Default frame is the entire texture
            currFrame = new Frame();
            currFrame.x = 0;
            currFrame.y = 0;
            currFrame.width = World.Instance.GetTexture(textureID).Width;
            currFrame.height = World.Instance.GetTexture(textureID).Height;     

        }

        public override void Update(float deltaTime)
        {
            base.Update(deltaTime);

            // Update bounding box
            spriteBB.Min.X = Position.X - width * 0.5f;
            spriteBB.Min.Y = Position.Y - height * 0.5f;
            spriteBB.Max.X = Position.X + width * 0.5f;
            spriteBB.Max.Y = Position.Y + height * 0.5f;
        }

        float scale;
        // ***TJS - Used to draw portions of textures
        public override void Draw(SpriteBatch spriteBatch)
        {
            Texture2D texture = World.Instance.GetTexture(TextureID);

            
            // Green - Blue - Orange - Red
            Rectangle drawRect = new Rectangle();
            if (shape == SquareSpriteShape.SQUARE)
            {
                //Draw Squares;
                switch (color)
                {
                    case SquareSpriteColor.GREEN:
                        drawRect = new Rectangle(98      , 1266, 174, 174);
                        break;
                    case SquareSpriteColor.BLUE:
                        drawRect = new Rectangle(98 + 500, 1266, 174, 174);
                        break;

                    case SquareSpriteColor.ORANGE:
                        drawRect = new Rectangle(84 + 1000, 1266, 174, 174);
                        break;
                    case SquareSpriteColor.RED:
                        drawRect = new Rectangle(70 + 1500, 1266, 174, 174);
                        break;
                    default:
                        break;
                }
            }
            else if (shape == SquareSpriteShape.SMALLRECT)
            {            
                //Draw Small Rectangles;
                switch (color)
                {
                    case SquareSpriteColor.GREEN:
                        drawRect = new Rectangle(98      ,  834, 100, 174);
                        break;
                    case SquareSpriteColor.BLUE:
                        drawRect = new Rectangle(98 + 500,  834, 100, 174);
                        break;

                    case SquareSpriteColor.ORANGE:
                        drawRect = new Rectangle(84 + 1000, 834, 100, 174);
                        break;
                    case SquareSpriteColor.RED:
                        drawRect = new Rectangle(70 + 1500, 834, 100, 174);
                        break;
                    default:
                        break;
                }

            }
            else if (shape == SquareSpriteShape.MEDRECT)
            {
                //Draw Medium Rectangles
                switch (color)
                {
                    case SquareSpriteColor.GREEN:
                        drawRect = new Rectangle(254      ,  834, 102, 318);
                        break;
                    case SquareSpriteColor.BLUE:
                        drawRect = new Rectangle(254 + 500,  834, 102, 318);
                        break;

                    case SquareSpriteColor.ORANGE:
                        drawRect = new Rectangle(240 + 1000, 834, 102, 318);
                        break;
                    case SquareSpriteColor.RED:
                        drawRect = new Rectangle(226 + 1500, 834, 102, 318);
                        break;
                    default:
                        break;
                }
            }
            else if (shape == SquareSpriteShape.LARGERECT)
            {
                //Draw Large Rectangles
                switch (color)
                {
                    case SquareSpriteColor.GREEN:
                        drawRect = new Rectangle(398       , 834, 102, 606);
                        break;
                    case SquareSpriteColor.BLUE:
                        drawRect = new Rectangle(398 + 500 , 834, 102, 606);
                        break;

                    case SquareSpriteColor.ORANGE:
                        drawRect = new Rectangle(384 + 1000, 834, 102, 606);
                        break;
                    case SquareSpriteColor.RED:
                        drawRect = new Rectangle(370 + 1500, 834, 102, 606);
                        break;
                    default:
                        break;
                }
            }
            

            // Need to scale down sprite from 164px to 80px and draw only one portion
            scale = 80.0f / 174.0f;
            Vector2 origin = new Vector2(drawRect.Width * .5f, drawRect.Height * .5f);                        
            spriteBatch.Draw(texture,Position, drawRect, Color.White, rotation, origin, scale, SpriteEffects.None,0.0f);
                    
        }

        // Return random ratation from 0 to 2*PI radians   
        public float randomRotation()
        {   
            double rot = rand.NextDouble();
            rot *= Math.PI;
            rot %= Math.PI;
            return (float)rot;
        }

        public float Rotation
        {
            get { return rotation; }
            set { rotation = value; }
        }

        public BoundingBox BoundBox
        {
            get { return spriteBB; }
        }

        public Rectangle Rectangle
        {
            get { return rect; } 
        }

        public Frame Frame
        {
            get { return currFrame; }
            set { currFrame = value; }
        }

        public SquareSpriteShape Shape
        {
            get { return shape; }
            set { shape = value; }
        }
    }

}